package cn.htsyb.synergy.security.web.captcha.filter;

import cn.htsyb.synergy.security.web.captcha.exception.CaptchaException;
import cn.htsyb.synergy.security.web.constant.WebSecurityConst;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @author lakeside hubin_yuan.410@hotmail.com
 * @version V1.0.0
 * @date 2022/5/22
 * @since 1.0
 */
@Setter
@Getter
@Component
@Slf4j
public class CaptchaValidatorFilter extends OncePerRequestFilter implements Filter {

    @Value("${spring.security.login.captcha.enabled:false}")
    private boolean captchaEnabled = true;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        if (captchaEnabled ) {
            Boolean hasBool= new AntPathRequestMatcher(WebSecurityConst.url_authenticate).matcher(request).isMatch();
            if (hasBool &&  "POST".equals(request.getMethod())) {
                try {
                    captchaValidator(request, response);
                }catch (CaptchaException e){
                    HttpSession session = request.getSession();
                    session.setAttribute("SPRING_SECURITY_LAST_EXCEPTION",e.getMessage());
                    throw  e;
                }
            }
        }
        filterChain.doFilter(request, response);
    }


    public boolean captchaValidator(HttpServletRequest request, HttpServletResponse response) {

        String requestVerifyCode = obtainRequestVerifyCode(request);
        String sessionVerifyCode = obtainSessionVerifyCode(request.getSession());
        if (!StringUtils.hasLength(requestVerifyCode)) {
            throw new CaptchaException(WebSecurityConst.message_captcha_request_empty);
        }
        if (!StringUtils.hasLength(sessionVerifyCode)) {
            throw new CaptchaException(WebSecurityConst.message_captcha_session_empty);
        }
        if (!requestVerifyCode.equalsIgnoreCase(sessionVerifyCode)) {
            throw new CaptchaException(WebSecurityConst.message_captcha_unmatched);
        }
        return true;
    }

    private String obtainRequestVerifyCode(HttpServletRequest request) {
        Object obj = request.getParameter(WebSecurityConst.parameter_logon_captcha);
        return null == obj ? "" : obj.toString();
    }

    protected String obtainSessionVerifyCode(HttpSession session) {
        Object obj = session.getAttribute(WebSecurityConst.parameter_logon_captcha);
        return null == obj ? "" : obj.toString();
    }
}
